/****************************************************
	文件：SchemeManager.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/10/11 17:18:36
	功能：配置表 管理器
*****************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using HTFW.Core;
using HTFW.Logger;
using UnityEngine;
using HTFW.Utility.Global;

namespace HTFW.Scheme
{
    public class SchemeManager : Singleton<SchemeManager>, IManager
    {
        /// <summary>
        /// 配置表数据缓存
        /// </summary>
        Dictionary<E_Scheme, object> mSchemeDataDict;

        /// <summary>
        /// 配置表资源引用
        /// </summary>
        Dictionary<E_Scheme, TextAsset> mSchemeRefDict;

        public void Init(params object[] args)
        {
            mSchemeDataDict = new Dictionary<E_Scheme, object>();
            mSchemeRefDict = new Dictionary<E_Scheme, TextAsset>();
        }

        public void Dispose()
        {
            mSchemeDataDict = null;
            mSchemeRefDict = null;
        }

        /// <summary>
        /// 加载指定 Scheme 数据
        /// </summary>
        /// <param name="scheme">配置表</param>
        /// <returns></returns>
        public T Load<T>(E_Scheme scheme) where T : class, new()
        {
            object data = null;
            if (mSchemeDataDict.TryGetValue(scheme, out data))
            {
                HLog.Debug($"配置表 {Enum.GetName(typeof(E_Scheme), scheme)} 已加载过，直接从缓存中获取配置表数据");
                return (T) data;
            }
            else
            {
                string schemeName = Enum.GetName(typeof(E_Scheme), scheme); //枚举名和配置表文件名一致
                string path = string.Format($"{SchemeDefine.PATH_SCHEMES_BINARY_FOLDER}{schemeName}.bytes");
                HLog.Debug($"加载配置表：{schemeName}\nPath：{path}");
                TextAsset textAsset = HTDriver.GlobalContext.ResContext.RObject.LoadSync<TextAsset>(path);
                if (textAsset == null)
                {
                    HLog.Error($"加载配置表出错！配置表（{schemeName}）不存在，\n路径：{path}");
                    return null;
                }

                try
                {
                    using (MemoryStream ms = new MemoryStream(textAsset.bytes))
                    {
                        BinaryFormatter bf = new BinaryFormatter();
                        data = bf.Deserialize(ms);
                    }
                }
                catch (Exception e)
                {
                    HLog.Error($"加载配置表 {schemeName} 出错；\nError：{e}");
                }

                mSchemeRefDict.Add(scheme, textAsset);

                mSchemeDataDict.Add(scheme, data);
                return (T) data;
            }
        }

        /// <summary>
        /// 获取配置表数据
        /// </summary>
        /// <param name="scheme">配置表</param>
        /// <returns></returns>
        public T Get<T>(E_Scheme scheme) where T : class, new()
        {
            object data = null;
            if (mSchemeDataDict.TryGetValue(scheme, out data) == false || data == null)
            {
                HLog.Error($"尚未加载配置表：{Enum.GetName(typeof(E_Scheme), scheme)}");
                return null;
            }

            return (T) data;
        }

        /// <summary>
        /// 卸载配置表资源
        /// </summary>
        /// <param name="scheme">配置表</param>
        /// <returns></returns>
        public bool Unload(E_Scheme scheme)
        {
            if (mSchemeRefDict.TryGetValue(scheme, out TextAsset data))
            {
                HTDriver.GlobalContext.ResContext.RObject.Unload(data, true);
                mSchemeRefDict.Remove(scheme);
                mSchemeDataDict.Remove(scheme);
                return true;
            }

            HLog.Warning($"不能卸载尚未加载的配置表资源：{scheme}");
            return false;
        }
    }
}